package server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayDeque;
import java.util.Deque;

public class HttpConnector implements Runnable{
   int minProcessors = 3;
   int maxProcessors = 10;
   int curProcessors = 0;

   Deque<HttpProcessor> processors = new ArrayDeque<>();

    public void run() {
        ServerSocket serverSocket = null;
        int port = 8080;
        try {
            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }

        for(int i = 0; i < minProcessors; i++) {
            HttpProcessor processor = new HttpProcessor(this);
            processor.start();
            processors.push(processor);
        }

        curProcessors = minProcessors;

        while (true) {
            Socket socket = null;
            try {
                socket = serverSocket.accept();
                HttpProcessor processor = createProcessor();
                if(processor == null) {
                    socket.close();
                    continue;
                }
                processor.assign(socket);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private HttpProcessor createProcessor() {
        synchronized (processors) {
            if(processors.size() > 0) {
                return (HttpProcessor) processors.pop();
            }
            if(curProcessors < maxProcessors) {
                return newProcessor();
            } else {
                return null;
            }
        }
    }
    public void start() {
        Thread thread = new Thread(this);
        thread.start();
    }

    private HttpProcessor newProcessor() {
        HttpProcessor processor = new HttpProcessor(this);
        processor.start();
        processors.push(processor);
        curProcessors++;
        return (HttpProcessor)processors.pop();
    }

    void recycle(HttpProcessor processor) {
        processors.push(processor);
    }
}
